package search_res_tab

import (
	"file_explorer/common/log"
	"file_explorer/common/util"
	"file_explorer/model"
	"file_explorer/service/eventbus"
	"file_explorer/service/third_program"
	"file_explorer/view/packed_widgets"
	"file_explorer/view/store"

	"fyne.io/fyne/v2"
	"github.com/samber/lo"
)

type FileList struct {
	*packed_widgets.Table

	tabCtx *store.SearchResTabContext
}

// 从context回写CheckList状态，用于排序后还原选中项
func (fileList *FileList) reloadCheckList() {
	if len(fileList.tabCtx.CheckedList) == 0 {
		return
	}
	checkItemSet := lo.SliceToMap(fileList.tabCtx.CheckedList, func(item *model.FileInfo) (*model.FileInfo, struct{}) {
		return item, struct{}{}
	})
	checkIndexList := lo.FilterMap(fileList.tabCtx.FileInfos, func(item *model.FileInfo, index int) (int, bool) {
		if _, ok := checkItemSet[item]; ok {
			return index, true
		}
		return 0, false
	})
	fileList.Checklist.SetCheckIndexList(checkIndexList)
}

func NewFileList(tabCtx *store.SearchResTabContext) *FileList {
	fileList := &FileList{
		tabCtx: tabCtx,
		Table:  packed_widgets.NewTable(),
	}

	fileList.Table.SetGetData(func(index int) interface{} {
		return tabCtx.FileInfos[index]
	})
	fileList.Table.SetGetDataLength(func() int {
		return len(tabCtx.FileInfos)
	})

	fileList.Table.AddColumn(
		packed_widgets.NewTableColumn().
			SetHeader("名称").
			SetWidth(200).
			SetIconGetter(func(data interface{}) fyne.Resource {
				return data.(*model.FileInfo).GetIcon()
			}).
			SetTextGetter(func(data interface{}) string { return data.(*model.FileInfo).Name }).
			SetOrderBy(func(asc bool) {
				fileList.tabCtx.SetSortFunc(
					util.GetComparatorByPriority[*model.FileInfo](
						asc,
						func(a, b *model.FileInfo) int {
							return int(b.Type) - int(a.Type)
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Name, b.Name)
						},
					),
				)
			}).
			SetDefaultOrder(),
	)

	fileList.Table.AddColumn(
		packed_widgets.NewTableColumn().
			SetHeader("目录").
			SetWidth(150).
			SetTextGetter(func(data interface{}) string { return data.(*model.FileInfo).Dir }).
			SetOrderBy(func(asc bool) {
				fileList.tabCtx.SetSortFunc(
					util.GetComparatorByPriority[*model.FileInfo](
						asc,
						func(a, b *model.FileInfo) int {
							return int(b.Type) - int(a.Type)
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Dir, b.Dir)
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Name, b.Name)
						},
					),
				)
			}).
			SetDefaultOrder(),
	)

	fileList.Table.AddColumn(
		packed_widgets.NewTableColumn().
			SetHeader("大小").
			SetWidth(80).
			SetTextGetter(func(data interface{}) string { return data.(*model.FileInfo).GetSize() }).
			SetOrderBy(func(asc bool) {
				fileList.tabCtx.SetSortFunc(
					util.GetComparatorByPriority[*model.FileInfo](
						asc,
						func(a, b *model.FileInfo) int {
							return int(b.Type) - int(a.Type)
						},
						func(a, b *model.FileInfo) int {
							return int(b.Size - a.Size)
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Name, b.Name)
						},
					),
				)
			}),
	)

	fileList.Table.AddColumn(
		packed_widgets.NewTableColumn().
			SetHeader("修改时间").
			SetWidth(150).
			SetTextGetter(func(data interface{}) string { return data.(*model.FileInfo).GetModifyTime() }).
			SetOrderBy(func(asc bool) {
				fileList.tabCtx.SetSortFunc(
					util.GetComparatorByPriority[*model.FileInfo](
						asc,
						func(a, b *model.FileInfo) int {
							return int(b.Type) - int(a.Type)
						},
						func(a, b *model.FileInfo) int {
							return int(b.ModifyTime.Unix() - a.ModifyTime.Unix())
						},
						func(a, b *model.FileInfo) int {
							return util.CmpText(a.Name, b.Name)
						},
					),
				)
			}),
	)

	fileList.Table.Build()

	// 双击文件
	fileList.Table.OnDoubleTapped = func(row int, col int) {
		fileInfo := fileList.tabCtx.FileInfos[row]
		if fileInfo.IsDir() {
			// 进入目录
			log.Info("打开目录：%s", fileInfo.GetPath())
			gCtx := tabCtx.GetGlobalContext()
			gCtx.AddTab(store.NewFileTabContext(gCtx, fileInfo.GetPath()))
		} else {
			// 打开文件
			log.Info("打开文件：%s", fileInfo.GetPath())
			third_program.GetCaller().OpenFile(fileInfo.GetPath())
		}
	}

	// 排序时同步checklist
	fileList.Table.RegisterConsumer(eventbus.EventKeyWidgetTableOrderChange, func(event *model.Event) {
		log.Info("搜索页排序变更，关键词：%s", tabCtx.Keyword)
		fileList.reloadCheckList()
	})

	// 文件列表checklist更新时同步到tab context内
	fileList.Table.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		log.Info("搜索页选中项变更，关键词：%s", tabCtx.Keyword)
		checkIndexList := fileList.Table.Checklist.GetCheckIndexList()
		fileList.tabCtx.CheckedList = make([]*model.FileInfo, 0, len(checkIndexList))
		for _, checkIndex := range checkIndexList {
			fileList.tabCtx.CheckedList = append(fileList.tabCtx.CheckedList, fileList.tabCtx.FileInfos[checkIndex])
		}
	})

	fileList.Table.Reset()

	return fileList
}
